perm filename DESIGN.2[CLS,LSP] blob
sn#827447 filedate 1986-10-28 generic text, type T, neo UTF8
\input macros
\def\bookline{\CLOS\ Specification}
\def\chapline{Design Rationale}
\beginChapter 5.{Common Lisp Object System Specification}%
{Design Rationale}{Design Rationale}
\endTitlePage
\beginSection{Introduction}
This document contains design rationale for many of the decisions that
were made in the course of writing this proposal. The history behind
these design decisions should be useful to anyone evaluating this
proposal.
\endSection%{Introduction}
\beginSection{Why DEFMETHOD Disallows Method Selection on Optional Parameters}
Currently defmethod only allows required parameters to have specializers
and be used for method selection. It would be useful to extend
defmethod to allow optional and keyword parameters to be used for method
selection. (It does not seem useful to allow rest, supplied-p, or
auxiliary parameters to be used for method selection.) This extension
has not been included in the present standard because it raises
technical issues about defaulting, consistency among methods, and order
of evaluation of initforms. Discussion among the group has revealed
that these issues are not well enough understood yet to be appropriate
for standardization.
Note that the effect of using an optional or keyword parameter for
method selection, from the point of view of the caller of the generic
function, can be achieved by using the :interface option to defgeneric
to turn the optional or keyword parameter of the generic function into a
required parameter of the methods. Thus all defaulting and order of
evaluation issues are centralized within the defgeneric, at the cost of
requiring the writer of a method to specify a different parameter list.
\endSection%{Why DEFMETHOD Disallows Method Selection on Optional Parameters}
\beginSection{Motivation for Several DEFCLASS Defaults}
In designing DEFCLASS we followed the principle that the definer of a
class should be able to decide which parts of the class are strictly
internal, and which are intended as an external interface. This design
principle is a guideline that encourages good data abstraction.
Therefore, all DEFCLASS options that make a slot visible (such that its
value could be read, written, or initialized) are turned off by default.
The definer of a class needs to make an explicit decision to make a slot
visible externally, by specifying one or more options.
Along the same lines, the :accessor-prefix and :reader-prefix options do
not have a default for the prefix. This represents a departure from the
analogous defstruct :conc-name option, which does have a default, which
is the name of the structure followed by a hyphen.
If the definer of the class uses the :accessor-prefix or :reader-prefix
option, the slots are part of the external interface. There are several
reasonable conventions for naming slot accessors and readers. The definer
of the class might choose "" as the prefix, or the name of the class, a
more general component, or the name of a protocol followed by a hyphen.
Since no single possibility is clearly better than the others, we provide
no default prefix and leave the decision to the definer of the class.
\endSection%{Motivation for Several DEFCLASS Defaults}
\beginSection{Assigning Classes to a Subset of Common Lisp Types}
Many of the predefined Common Lisp type specifiers have a class associated
with them. For example, an array is of type array, and of class array. A
class that corresponds to a predefined Common Lisp type specifier is called
a built-in class.
Every class has a corresponding type. However, not all types have a
corresponding class. This section presents the mapping of classes to types
and explains the rationale for excluding some types.
Users can write methods that dispatch on any primitive Lisp type that has a
corresponding class. However, it is not allowed to make an instance of a
built-in class with make-instance, nor to include a built-in class as a
super-class of a class.
The difference between built-in classes and user-defined classes is in the
implementation of instances. Instances of a built-in class are implemented
in a specialized way that does not permit subclassing. In some
implementations some classes documented as built-in might in fact be
implemented as user-defined classes, but portable programs cannot assume
this.
The specializer of a specialized-parameter in a defmethod lambda-list must be
a member of a limited subset of Common Lisp type-specifiers. It would be
useful to extend this to the full generality of Common Lisp
type-specifiers, but this raises technical issues that are not yet
appropriate for standardization. For example, deciding what to do when an
argument is an instance of two types, both of which have methods, but
neither is a subtype of the other. Another issue is the question of the
reliability of subtypep in some implementations. Dealing with not raises
yet another technical issue. For more information, see "Boolean Classes" by
D. McAllester and R. Zabih, a paper presented at the 1986 ACM First Annual
Conference on Object-Oriented Programming Systems, Languages, and
Applications.
Currently acceptable type-specifiers must be symbols (no lists are
permitted) in one of the following four categories:
1. t, the universal class.
2. The name of a user-defined class, defined with DEFCLASS.
3. The name of a structure, defined with DEFSTRUCT without using :type.
4. One of the following built-in class names:
array
bit-vector subclass of vector, array, sequence
character
compiled-function
complex subclass of number
cons subclass of list, sequence
double-float subclass of float, number
float subclass of number
hash-table
integer subclass of rational, number
list subclass of sequence
long-float subclass of float, number
null subclass of symbol, list, sequence
number
package
pathname
random-state
ratio subclass of rational, number
rational subclass of number
readtable
sequence
short-float subclass of float, number
single-float subclass of float, number
string subclass of vector, array, sequence
symbol
vector subclass of array, sequence
Converting a partial ordering to a total ordering for the sake of brevity,
classes are ranked here in order from most specific to most general:
rational float number symbol list vector array sequence
The following types could have been allowed as classes, but we have
excluded them for the reasons shown:
- Types too specific to be useful to put methods on: bit, keyword,
standard-char, string-char
- The type implies an implementation, not behavior: bignum,
fixnum, simple-array, simple-bit-vector, simple-string,
simple-vector
- Specification of the type is too vague: common, function, stream
- This is the same as (not cons), and we are not yet dealing with
not: atom
- No object can be an instance of this type: nil
The following types are also excluded as classes: add, member, mod, not,
or, satisfies, values.
Another way of looking at these choices is that a type is included only if
there is a function for making objects of this type, such as make-array.
bit, fixnum, and bignums are excluded because there are no separate
functions for making objects of those types. function is excluded because
there is no function to make functions, but compiled-function is included
because the compile function exists. stream is excluded because there is
no single function to make streams, and in fact many different types of
objects can be streams. This line of reasoning is not watertight, but it's
a pretty good heuristic.
Individual implementations can extend this to allow other type-specifiers.
Also individual implementations can add additional subclass relationships
as long as they do not violate Common Lisp the Language pp.33-5. For
example, readtable can be a subclass of array, and hence inherit methods
from array, in some implementations. It is important that the subclass
relationships among built-in classes be identical with the subtype
relationships among their corresponding types, so that the class system is
merged seamlessly with the type system.
\endSection%{Assigning Classes to a Subset of Common Lisp Types}
\beginSection{Method Selection by Predications More General Than Classes}
This section should be considered a possible extension to the standard. It
is included in "Design Rationale" because it has been discussed in the
group.
The standard as currently proposed only allows method selection by the
classes of the arguments, or by equality to a given object, as in:
(QUOTE object). This could be extended in various ways. It is
important that any extensions to method selection remain consistent
with, and a subset of, Common Lisp type-specifiers, rather than
introducing a whole new type system in parallel with the existing one.
Method selection could be extended to allow the full generality of Common
Lisp type-specifiers; that is, arbitrary predications. The problem with
this is that there can be predications that have objects in common, but do
not have a subtype/supertype relationship. Thus if methods are defined for
both predications, it is not clear which method has precedence. This is in
contrast to classes; if an object is an instance of two classes, one class
is always a component of the other, and the subtype/supertype relationship
can always be determined.
Rather than totally ruling out method selection by predications because it
might not be clear which method has precedence, predications could be
allowed, with the requirement that an error is signalled if such a method
ambiguity is actually encountered. This would not prevent users from
defining a method on one predication, but would preclude defining methods
on two overlapping predications such as (integer 1 100) and (integer 50
144), which would signal an error if and only if the argument was an
integer between 50 and 100.
Subtype/supertype relationships can be computed for many of the most useful
predications, but in the most general case where this ordering is not
computable, the semantics are still well-defined, but not as amenable to
optimization. At run-time the value of the argument must be tested against
both predications. If both are true an error must be signalled, otherwise
the applicable method is well-defined. This extra testing of predications
can be minimized by converting the type-specifiers to canonical form. The
details are not given here because this is evidently an unexplored area
that is not yet appropriate for standardization.
\endSection%{Method Selection by Predications More General Than Classes}
\endChapter
\bye